package com.shnu.work.controller;

import com.google.gson.Gson;
import com.shnu.work.entity.DeepLearningDataDocumentsEntity;
import com.shnu.work.entity.UserDataWhileUsingEntity;
import com.shnu.work.entity.UserInformationEntity;
import com.shnu.work.service.IUserDataWhileUsingService;
import com.shnu.work.service.IUserInformationService;
import com.shnu.work.util.NewRedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.util.List;
import java.util.Set;

/**
 * 和用户相关的Controller
 *
 * @author Shinomiya Kaguya
 */
@Slf4j
@Controller
@RequestMapping("/user")
public class UserController {
    private final Gson gson = new Gson();
    @Autowired
    private IUserInformationService userInformationService;
    @Autowired
    private IUserDataWhileUsingService userDataWhileUsingService;
    @Autowired
    private MongoTemplate mongoTemplate;

    @RequestMapping("/getUserInfo")
    public ModelAndView getUserInfo(ModelAndView modelAndView, HttpSession session) {
        String loginUser = (String) session.getAttribute("login_user");
        if (!StringUtils.isBlank(loginUser)) {
            UserInformationEntity userInfo = userInformationService.getUserInformationEntityByUserAccount(loginUser);
            log.info("userInfo:{}", gson.toJson(userInfo));
            modelAndView.addObject("userInfo", userInfo);
        }
        modelAndView.setViewName("/userinfo");
        return modelAndView;
    }

    @RequestMapping("/updateUserInfo")
    public String updateUserInfo(@Param("userName") String userName,
                                 @Param("userAccount") String userAccount,
                                 @Param("userSex") Integer userSex,
                                 @Param("userSignature") String userSignature) {
        UserInformationEntity resultEntity = userInformationService.getUserInformationEntityByUserAccount(userAccount);
        log.info("resultEntity:{}", gson.toJson(resultEntity));
        resultEntity.setUserName(userName);
        resultEntity.setUserSex(userSex);
        if (!StringUtils.isBlank(userSignature)) {
            resultEntity.setUserSignature(userSignature);
        }
        userInformationService.saveUser(resultEntity);

        return "redirect:/user/getUserInfo";
    }

    @RequestMapping("/backToHomepage")
    public String backToHomepage() {
        return "/index";
    }

    @RequestMapping("/getSensorInfo")
    public ModelAndView getSensorInfo(ModelAndView modelAndView, HttpSession session) {
        String loginUser = (String) session.getAttribute("login_user");
        listSensorData(modelAndView, loginUser);
        modelAndView.setViewName("/sensorinfo");
        return modelAndView;
    }

    @RequestMapping("/listUserDataByIdAndTime")
    public ModelAndView listUserDataByIdAndTime(HttpSession session, ModelAndView modelAndView,
                                                @Param("lUserDocumentTime") String lUserDocumentTime,
                                                @Param("lDeviceId") Long lDeviceId) {
        List<UserDataWhileUsingEntity> allUndeleted = null;
        String loginUser = (String) session.getAttribute("login_user");
        NewRedisUtils redisUtils = NewRedisUtils.getRedisUtil();
        UserInformationEntity userAccount = this.userInformationService.getUserInformationEntityByUserAccount(loginUser);
        try {
            if (lDeviceId != null && !StringUtils.isBlank(lUserDocumentTime)) {
                allUndeleted = userDataWhileUsingService.listUserDataByDeviceIdAndUserDocumentTimeAndUserId(lDeviceId, lUserDocumentTime, userAccount.getId());
                log.info("userDataList Before Redis:{}", gson.toJson(allUndeleted));
                Set<String> redisUserData = redisUtils.keys(2, "location_info_" + userAccount.getUserAccount() + "*" + lDeviceId + "*");
                redisUserData.stream().map(key -> redisUtils.get(2, key)).map(value -> gson.fromJson(value, UserDataWhileUsingEntity.class)).filter(userDataWhileUsingEntity -> new Integer(1).equals(userDataWhileUsingEntity.getIsDeleted())).forEach(allUndeleted::add);
                log.info("userDataList After Redis:{}", gson.toJson(allUndeleted));
            }
            if (lDeviceId == null && !StringUtils.isBlank(lUserDocumentTime)) {
                allUndeleted = userDataWhileUsingService.listUserDataByUserDocumentTimeAndUserId(lUserDocumentTime, userAccount.getId());
                log.info("userDataList Before Redis:{}", gson.toJson(allUndeleted));
                Set<String> redisUserData = redisUtils.keys(2, "location_info_" + lUserDocumentTime + "*");
                redisUserData.stream().map(key -> redisUtils.get(2, key)).map(value -> gson.fromJson(value, UserDataWhileUsingEntity.class)).filter(userDataWhileUsingEntity -> new Integer(1).equals(userDataWhileUsingEntity.getIsDeleted())).forEach(allUndeleted::add);
                log.info("userDataList After Redis:{}", gson.toJson(allUndeleted));
            }
            if (lDeviceId != null && StringUtils.isBlank(lUserDocumentTime)) {
                allUndeleted = userDataWhileUsingService.listUserDataByDeviceIdAndUserId(lDeviceId, userAccount.getId());
                log.info("userDataList Before Redis:{}", gson.toJson(allUndeleted));
                Set<String> redisUserData = redisUtils.keys(2, "location_info_" + lUserDocumentTime + "*" + lDeviceId + "*");
                redisUserData.stream().map(key -> redisUtils.get(2, key)).map(value -> gson.fromJson(value, UserDataWhileUsingEntity.class)).filter(userDataWhileUsingEntity -> new Integer(1).equals(userDataWhileUsingEntity.getIsDeleted())).forEach(allUndeleted::add);
                log.info("userDataList After Redis:{}", gson.toJson(allUndeleted));
            }
            if (lDeviceId == null && StringUtils.isBlank(lUserDocumentTime)) {
                log.info("userDataList Before Redis:{}", gson.toJson(allUndeleted));
                allUndeleted = userDataWhileUsingService.listUserDataWhileUsingEntitiesByUserId(userAccount.getId());
                Set<String> redisUserData = redisUtils.keys(2, "location_info_*");
                redisUserData.stream().map(key -> redisUtils.get(2, key)).map(value -> gson.fromJson(value, UserDataWhileUsingEntity.class)).filter(userDataWhileUsingEntity -> new Integer(1).equals(userDataWhileUsingEntity.getIsDeleted())).forEach(allUndeleted::add);
                log.info("userDataList After Redis:{}", gson.toJson(allUndeleted));
            }
        } catch (Exception exception) {
            log.error("查询出错", exception);
            allUndeleted = userDataWhileUsingService.listUserDataWhileUsingEntitiesByUserId(userAccount.getId());
            Set<String> redisUserData = redisUtils.keys(2, "location_info_*");
            redisUserData.stream()
                    .map(key -> redisUtils.get(2, key)).map(value -> gson.fromJson(value, UserDataWhileUsingEntity.class))
                    .filter(userDataWhileUsingEntity -> new Integer(1).equals(userDataWhileUsingEntity.getIsDeleted()))
                    .forEach(allUndeleted::add);
            log.info("userDataList After Redis:{}", gson.toJson(allUndeleted));
        }


        log.info("listUserDataByIdAndTime 查询结果:{}", gson.toJson(allUndeleted));

        modelAndView.addObject("userDataList", allUndeleted);
        modelAndView.setViewName("/sensorinfo");
        return modelAndView;
    }

    @RequestMapping("/getSensorDataGatheringInfo")
    public ModelAndView getSensorDataGatheringInfo(ModelAndView modelAndView) {
        Query query = new Query();
        query.addCriteria(Criteria.where("title").is("传感器数据采集说明"));
        DeepLearningDataDocumentsEntity sensorGatheringData = mongoTemplate.findOne(query, DeepLearningDataDocumentsEntity.class);
        log.info("getSensorDataGatheringInfo sensorData:{}", gson.toJson(sensorGatheringData));
        modelAndView.addObject("sensorGatheringData", sensorGatheringData);
        modelAndView.setViewName("/datagathering");
        return modelAndView;
    }

    @RequestMapping("/getAboutUsInfo")
    public ModelAndView getAboutUsInfo(ModelAndView modelAndView) {
        Query query = new Query();
        query.addCriteria(Criteria.where("title").is("关于我们"));
        DeepLearningDataDocumentsEntity aboutUsData = mongoTemplate.findOne(query, DeepLearningDataDocumentsEntity.class);
        log.info("getSensorDataGatheringInfo aboutUsData:{}", gson.toJson(aboutUsData));
        modelAndView.addObject("aboutUsData", aboutUsData);
        modelAndView.setViewName("/aboutus");
        return modelAndView;
    }

    private void listSensorData(ModelAndView modelAndView, String loginUser) {
        if (!StringUtils.isBlank(loginUser)) {
            NewRedisUtils redisUtils = NewRedisUtils.getRedisUtil();
            UserInformationEntity userInfo = userInformationService.getUserInformationEntityByUserAccount(loginUser);
            log.info("userInfo:{}", gson.toJson(userInfo));
            List<UserDataWhileUsingEntity> userDataList =
                    userDataWhileUsingService.listUserDataWhileUsingEntitiesByUserId(userInfo.getId());
            log.info("userDataList Before Redis:{}", gson.toJson(userDataList));
            String queryKey = "location_info_" + userInfo.getUserAccount() + "_*";
            log.info("listSensorData queryKey:{}", queryKey);
            Set<String> redisUserData = redisUtils.keys(2, queryKey);
            redisUserData.stream()
                    .map(key -> redisUtils.get(2, key)).map(value -> gson.fromJson(value, UserDataWhileUsingEntity.class))
                    .filter(userDataWhileUsingEntity -> new Integer(1).equals(userDataWhileUsingEntity.getIsDeleted()))
                    .forEach(userDataList::add);
            log.info("userDataList After Redis:{}", gson.toJson(userDataList));
            modelAndView.addObject("userDataList", userDataList);
        }
    }
}
